home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
019a
/
opbgd113.zip
/
OPBIGED.IN1
< prev
next >
Wrap
Text File
|
1991-10-21
|
42KB
|
1,563 lines
procedure BigEditor.GoToMarker(var M : MarkerRec);
begin
with M do begin
if LP = nil then exit;
GoToLinePtr(LP);
CursorToCol(CP);
end;
end;
function BigEditor.MemForBlock : LongInt;
var
P : PLine;
L : LongInt;
begin
P := beBlockBegin.LP;
L := LongInt(P^.Size) + SizeOf(LineNode);
while (P <> nil) and (P <> beBlockEnd.LP) do begin
P := PLine(P^.dlNext);
Inc(L, LongInt(P^.Size) + SizeOf(LineNode));
end;
MemForBlock := L;
end;
function BigEditor.BlockContiguous : Boolean;
var
P : PLine;
begin
BlockContiguous := False;
if (beBlockBegin.LP = nil) or (beBlockEnd.LP = nil) then exit;
if (beBlockBegin.LP = beBlockEnd.LP) then begin
BlockContiguous := (beBlockEnd.CP >= beBlockEnd.CP);
exit;
end;
P := beBlockBegin.LP;
while P <> nil do begin
if P = beBlockEnd.LP then begin
BlockContiguous := True;
exit;
end;
P := PLine(P^.dlNext);
end;
end;
function BigEditor.LineInBlock(P : PLine) : Boolean;
var
N : PLine;
begin
LineInBlock := False;
if not BlockContiguous then exit;
N := beBlockBegin.LP;
while N <> nil do begin
if N = P then begin
LineInBlock := True;
exit;
end;
if N = beBlockEnd.LP then exit;
N := PLine(N^.dlNext);
end;
end;
function BigEditor.CursorInBlock(ChkCol : Boolean) : Boolean;
var
P : PLine;
begin
CursorInBlock := False;
P := CurLine;
if not LineInBlock(P) then exit;
if P = beBlockBegin.LP then
CursorInBlock := ((not(ChkCol)) or (beBlockBegin.CP <= CurCol))
else if P = beBlockEnd.LP then
CursorInBlock := ((not(ChkCol)) or (beBlockEnd.CP >= CurCol))
else
CursorInBlock := True;
end;
procedure BigEditor.CharsInserted(P : PLine; At, Num : Integer);
var
I : Integer;
procedure Adjust(var M : MarkerRec; TextMkr : Boolean);
var
TC : Integer;
begin
with M do
if (P = LP) and (CP >= At) then begin
TC := CP;
if (TextMkr) or (TC > At) then
if Num > 0 then
Inc(TC, Num)
else
Dec(TC, Abs(Num));
if TC < At then
CP := At
else
CP := TC;
end;
end;
begin
Adjust(beLastPosition, True);
if P = beBlockBegin.LP then
Adjust(beBlockBegin, False);
if P = beBlockEnd.LP then
Adjust(beBlockEnd, False);
if not BlockContiguous then
ClearLongFlag(beOptions, beBlockOn)
else
ConnectBlocking;
if beMarkerFlags <> 0 then
for I := 0 to MaxMarker do
if P = beMarkers[i].LP then
Adjust(beMarkers[i], True);
end;
procedure BigEditor.LineDeleted(P : PLine);
var
PN : Word;
I : Integer;
procedure Adjust(var M : MarkerRec; MT : MarkerType);
var
L : Word;
N : Integer;
begin
with M do begin
if LP = P then
if MT = mtMarker then
LP := nil
else begin
if MT = mtBlockBegin then
LP := PLine(LP^.dlNext)
else
LP := PLine(LP^.dlPrev);
CP := 0;
end;
end;
end;
begin
Adjust(beLastPosition, mtMarker);
PN := LList^.Num(P);
if beBlockBegin.LP <> nil then
Adjust(beBlockBegin, mtBlockBegin);
if beBlockEnd.LP <> nil then
Adjust(beBlockEnd, mtBlockEnd);
if not BlockContiguous then
ClearLongFlag(beOptions, beBlockOn)
else
ConnectBlocking;
if beMarkerFlags <> 0 then
for I := 0 to MaxMarker do
Adjust(beMarkers[i], mtMarker);
end;
procedure BigEditor.LinesBroken(P : PLine; At : Integer);
var
PN : Word;
I : Integer;
procedure Adjust(var M : MarkerRec);
begin
with M do
if (LP = P) and (CP >= At) then begin
LP := PLine(LP^.dlNext);
Dec(CP, At);
if CP < 0 then CP := 0;
end;
end;
begin
Adjust(beLastPosition);
PN := LList^.Num(P);
if beBlockBegin.LP <> nil then
Adjust(beBlockBegin);
if beBlockEnd.LP <> nil then
Adjust(beBlockEnd);
if not BlockContiguous then
ClearLongFlag(beOptions, beBlockOn)
else
ConnectBlocking;
if beMarkerFlags <> 0 then
for I := 0 to MaxMarker do
Adjust(beMarkers[i]);
end;
procedure BigEditor.LinesJoined(P : PLine; At : Integer);
var
I : Integer;
procedure Adjust(var M : MarkerRec);
begin
with M do
if LP = P then begin
LP := PLine(LP^.dlPrev);
Inc(CP, At);
end;
end;
begin
Adjust(beLastPosition);
if beBlockBegin.LP <> nil then
Adjust(beBlockBegin);
if beBlockEnd.LP <> nil then
Adjust(beBlockEnd);
if not BlockContiguous then
ClearLongFlag(beOptions, beBlockOn)
else
ConnectBlocking;
if beMarkerFlags <> 0 then
for I := 0 to MaxMarker do
Adjust(beMarkers[i]);
end;
procedure BigEditor.ConnectBlocking;
{-walks list, connection proper block marks}
var
P : PLine;
B : Boolean;
begin
B := False;
P := PLine(LList^.Head);
while P <> nil do begin
if P = beBlockBegin.LP then
B := True;
P^.Blocked := B;
if P = beBlockEnd.LP then
B := False;
P := PLine(P^.dlNext);
end;
end;
procedure BigEditor.CleanBlocking;
{-clears existing blocking}
var
P : PLine;
begin
P := PLine(LList^.Head);
while P <> nil do begin
P^.Blocked := False;
P := PLine(P^.dlNext);
end;
end;
procedure BigEditor.MarkWordAsBlock;
label
Again;
var
I : Integer;
C : Integer;
function IsAlpha(C : Char) : Boolean;
begin
IsAlpha := not (C in WordDelims);
end;
begin
GetCurLine;
I := LenAsc(Work^);
if I = 0 then begin
GotError(epNonFatal,'Empty line');
exit;
end;
Dec(I);
C := CurCol;
if C > I then
C := I;
Again:
if IsAlpha(Work^[C]) then begin
while (C >= 0) and (IsAlpha(Work^[C])) do
Dec(C);
Inc(C);
end
else if C = I then begin
while (C >= 0) and (Work^[C] in WordDelims) do
Dec(C);
if (C >= 0) then
goto Again;
end
else begin
while (C < I) and (Work^[C] in WordDelims) do
Inc(C);
if C > I then begin
C := I;
goto Again;
end;
end;
if (C < 0) or (C > I) then begin
GotError(epNonFatal, 'Can''t define line limits');
exit;
end;
beBlockBegin.CP := C;
while (C <= I) and (IsAlpha(Work^[C])) do
Inc(C);
beBlockEnd.CP := C;
beBlockBegin.LP := Cur;
beBlockEnd.LP := Cur;
if BlockContiguous then
ConnectBlocking;
SetLongFlag(beOptions, beBlockOn+beForceRedraw);
end;
procedure BigEditor.ChangeCaseBlock(CT : beChangeCaseType);
var
P : PLine;
procedure ChangeCharPrim(var C : Char);
begin
case CT of
beToUpper:
C := Upcase(C);
beToLower:
C := Locase(C);
else begin
if C in ['A'..'Z'] then
C := Locase(C)
else
C := Upcase(C);
end;
end;
end;
procedure ChangeLinePrim(L : AsciiZPtr; At, Len : Integer);
var
M,N : Integer;
begin
M := LenAsc(L^)-1;
if M < At then exit;
if M > (At+Len) then
M := At+Len;
for N := At to M do
ChangeCharPrim(L^[N]);
end;
begin
if (not(BlockContiguous)) or (not(LongFlagIsSet(beOptions, beBlockOn))) then exit;
P := beBlockBegin.LP;
if P = beBlockEnd.LP then
{block is in a single line}
ChangeLinePrim(P^.St, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP)
else begin
ChangeLinePrim(P^.St, beBlockBegin.CP, AbsMaxAsciiZ);
P := PLine(P^.dlNext);
while P <> beBlockEnd.LP do begin
ChangeLinePrim(P^.St, 0, AbsMaxAsciiZ);
P := PLine(P^.dlNext);
end;
ChangeLinePrim(P^.St, 0, beBlockEnd.CP);
end;
SetLongFlag(beOptions, beForceRedraw);
end;
function BigEditor.BlockToList(var L : LineList) : Boolean;
var
P, N : PLine;
Siz : LongInt;
begin
BlockToList := False;
L.Clean;
if beBlockBegin.LP = beBlockEnd.LP then begin
{a single line to copy}
CopyAsc(beBlockBegin.LP^.St^, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP,
Temp^);
New(P, Init(Temp));
if P = nil then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
L.Append(P);
end
else begin
{multiline block to copy}
N := beBlockBegin.LP;
{copy starting line}
CopyAsc(N^.St^, beBlockBegin.CP, AbsMaxAsciiZ, Temp^);
New(P, Init(Temp));
if P = nil then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
L.Append(P);
N := PLine(N^.dlNext);
while N <> beBlockEnd.LP do begin
{copy intermediate line(s)}
New(P, Init(N^.St));
if P = nil then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
L.Append(P);
N := PLine(N^.dlNext);
end;
{copy blockend line}
CopyAsc(N^.St^, 0, beBlockEnd.CP, Temp^);
New(P, Init(Temp));
if P = nil then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
L.Append(P);
end;
BlockToList := True;
end;
procedure BigEditor.BlockFromList(var L : LineList);
label
Breakout;
var
P, N, X : PLine;
begin
if L.Size = 0 then exit;
GetCurLine;
if L.Size = 1 then begin
{a single line to insert:}
if CurCol > Cur^.lnLen then
AscPad(Work^, CurCol, Work^);
{update the line}
InsertAsc(PLine(L.Head)^.St^, Work^, CurCol);
Status := Cur^.lnUpdate(Work);
if Status <> 0 then goto BreakOut;
{update blockmarks}
beBlockBegin.LP := Cur;
beBlockBegin.CP := CurCol;
beBlockEnd.LP := Cur;
beBlockEnd.CP := beBlockBegin.CP + LenAsc(PLine(L.Head)^.St^);
end
else begin
{multiline block to insert: first split the current line at the cursor}
P := SplitLine(Cur, CurCol);
if P = nil then goto BreakOut;
LList^.Place(P, Cur);
{add the first block line}
N := PLine(L.Head);
ConcatAsc(Work^, N^.St^, Work^);
Status := Cur^.lnUpdate(Work);
if Status <> 0 then goto BreakOut;
{update blockbegin}
beBlockBegin.LP := Cur;
beBlockBegin.CP := CurCol;
{walk list inserting intermediate lines}
X := Cur;
N := PLine(N^.dlNext);
while N <> nil do begin
New(P, Init(N^.St));
if P = nil then goto BreakOut;
LList^.Place(P, X);
X := PLine(X^.dlNext);
N := PLine(N^.dlNext);
end;
{update beBlockEnd}
beBlockEnd.LP := X;
beBlockEnd.CP := LenAsc(X^.St^);
{concat following line}
P := PLine(X^.dlNext);
if P <> nil then begin
GetTemp(P);
ConcatAsc(X^.St^, Temp^, Work^);
Status := X^.lnUpdate(Work);
if Status <> 0 then goto Breakout;
LList^.Delete(P);
end;
end;
ConnectBlocking;
SetLongFlag(beOptions, beModified+beForceRedraw+beBlockOn);
exit;
BreakOut:
CleanBlocking;
FillChar(beBlockBegin, SizeOf(beBlockBegin), 0);
FillChar(beBlockEnd, SizeOf(beBlockEnd), 0);
GotError(epFatal+ecOutOfMemory, emInsufficientMemory);
end;
function BigEditor.DeleteBlockPrim : Boolean;
var
P, N : PLine;
I : Word;
begin
DeleteBlockPrim := False;
if not BlockContiguous then exit;
if beBlockBegin.LP = beBlockEnd.LP then begin
{single line block}
N := CurLine;
P := beBlockBegin.LP;
GetWork(P);
DeleteAsc(Work^, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP);
Status := P^.lnUpdate(Work);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
if P = N then
if CurCol > beBlockBegin.CP then
ChCursor(-(beBlockEnd.CP-beBlockBegin.CP));
end
else begin
N := beBlockBegin.LP;
GoToLineCol(LList^.Num(N), 0);
GetWork(N);
DeleteAsc(Work^, beBlockBegin.CP, AbsMaxAsciiZ);
while PLine(N^.dlNext) <> beBlockEnd.LP do begin
P := PLine(N^.dlNext);
LList^.Delete(P);
end;
P := beBlockEnd.LP;
GetTemp(P);
LList^.Delete(P);
DeleteAsc(Temp^, 0, beBlockEnd.CP);
ConcatAsc(Work^, Temp^, Work^);
Status := N^.lnUpdate(Work);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
end;
FillChar(beBlockBegin, SizeOf(beBlockBegin), 0);
FillChar(beBlockEnd, SizeOf(beBlockEnd), 0);
ClearLongFlag(beOptions, beBlockOn);
SetLongFlag(beOptions, beModified+beForceRedraw);
{if we erased the whole stream, make sure things are safe}
if LList^.Size = 0 then begin
Str2Asc('', Work^);
New(Top, Init(Work));
LList^.Append(Top);
LOfs := 0;
CPos := 1;
COfs := 0;
end;
DeleteBlockPrim := True;
end;
procedure BigEditor.CopyBlock;
var
Siz : LongInt;
begin
if (not(beOptionsAreOn(beBlockOn))) or (not(BlockContiguous)) then exit;
{make sure we've got enough mem to do the job}
Siz := MemForBlock * 2; {we need twice as much memory for a copy}
Siz := Siz + MemSafetySize;
if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
{store the block}
if not BlockToList(TList^) then exit;
{paste it in at the current location}
BlockFromList(TList^);
TList^.Clean;
end;
procedure BigEditor.MoveBlock;
var
C : Integer;
P : PLine;
Siz : LongInt;
begin
if (not(beOptionsAreOn(beBlockOn))) or (not(BlockContiguous)) then
exit;
{don't try to move the whole stream}
if (beBlockBegin.LP = PLine(LList^.Head)) and (beBlockEnd.LP = PLine(LList^.Tail)) then
exit;
{make sure we've got enough mem to do the job}
Siz := MemForBlock + MemSafetySize;
if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
{move the block: start by saving our current position}
P := PLine(LList^.Nth(TNum+LOfs));
C := CurCol;
{store the block}
if not BlockToList(TList^) then exit;
{delete the block in the main stream}
if not DeleteBlockPrim then exit;
{restore our display position in the stream}
GoToLinePtr(P);
CursorToCol(C);
{paste in the block}
BlockFromList(TList^);
TList^.Clean;
end;
procedure BigEditor.DeleteBlock;
var
L : Integer;
begin
if (not(beOptionsAreOn(beBlockOn))) or (not(CursorInBlock(True))) then exit;
if DeleteBlockPrim then ;
end;
function BigEditor.ReadBlockPrim(var Lst : LineList) : Boolean;
label
Breakout;
var
Buf : IOBuf;
F : Text;
FN : PathStr;
I : Integer;
P : PLine;
begin
ReadBlockPrim := False;
FN := '';
if not Edit(mcBlockRead, emBlockRead, True, True, 80, FN) then exit;
if not ExistFile(FN) then begin
GotError(epNonFatal+ecFileNotFound, emFileNotFound);
exit;
end;
Assign(F, FN);
SetTextBuf(F, Buf, MaxFBuf);
Reset(F);
I := IoResult;
if I <> 0 then begin
GotError(epNonFatal+I, emOpenError);
exit;
end;
Lst.Clean;
while not EOF(F) do begin
if not ReadLnAsc(F, Work^) then begin
GotError(epNonFatal+ecDeviceRead, emReadError);
goto Breakout;
end;
New(P, Init(Work));
if P = nil then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
goto BreakOut;
end;
Lst.Append(P);
end;
ReadBlockPrim := True;
Breakout:
Close(F); if IoResult = 0 then ;
end;
procedure BigEditor.ReadBlock;
begin
if not ReadBlockPrim(TList^) then exit;
BlockFromList(TList^);
end;
procedure BigEditor.WriteBlock(ToPrn : Boolean);
label
Breakout;
var
Buf : IOBuf;
F : Text;
FN : PathStr;
I : Integer;
P : PLine;
function WriteLine(P : AsciiZPtr) : Integer;
var
N : Integer;
begin
N := 0;
if not WriteAsc(F, P^) then
I := ecDeviceWrite
else begin
Write(F, ^M^J);
I := IoResult;
end;
WriteLine := I;
end;
begin
if (not(BlockContiguous)) or
(not(LongFlagIsSet(beOptions, beBlockOn))) then exit;
if ToPrn then
FN := 'LPT'+beLPTNum
else begin
FN := '';
if not Edit(mcBlockWrite, emBlockWrite, True, True, 80, FN) then exit;
if ExistFile(FN) then
if YesNo(0, 'File exists. Overwrite?', beNo, False) = beNo then exit;
end;
Assign(F, FN);
SetTextBuf(F, Buf, MaxFBuf);
Rewrite(F);
I := IoResult;
if I <> 0 then begin
GotError(epNonFatal+I, emOpenError);
exit;
end;
P := beBlockBegin.LP;
GetWork(P);
if P = beBlockEnd.LP then begin
DeleteAsc(Work^, beBlockEnd.CP, AbsMaxAsciiZ);
DeleteAsc(Work^, 0, beBlockBegin.CP);
I := WriteLine(Work);
if I <> 0 then
GotError(epNonFatal+I, emWriteError);
end
else begin
DeleteAsc(Work^, 0, beBlockBegin.CP);
I := WriteLine(Work);
if I <> 0 then begin
GotError(epNonFatal+I, emWriteError);
goto Breakout;
end;
P := PLine(P^.dlNext);
while P <> beBlockEnd.LP do begin
GetWork(P);
I := WriteLine(Work);
if I <> 0 then begin
GotError(epNonFatal+I, emWriteError);
goto Breakout;
end;
P := PLine(P^.dlNext);
end;
GetWork(P);
DeleteAsc(Work^, beBlockEnd.CP, AbsMaxAsciiZ);
I := WriteLine(Work);
if I <> 0 then
GotError(epNonFatal+I, emWriteError);
end;
Breakout:
Close(F); if IoResult <> 0 then ;
end;
procedure BigEditor.CopyToClipboard(Cut : Boolean);
var
Siz : LongInt;
begin
if (not(BlockContiguous)) then exit;
Siz := MemForBlock + MemSafetySize;
if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
if not BlockToList(Clipboard) then exit;
if not Cut then
ClearLongFlag(beOptions, beBlockOn)
else
if DeleteBlockPrim then ;
SetLongFlag(beOptions, beForceRedraw);
end;
procedure BigEditor.PasteFromClipboard;
begin
if Clipboard.Size > 0 then
BlockFromList(Clipboard);
end;
procedure BigEditor.IndentBlock(Spaces : Integer);
label
Breakout;
var
P : PLine;
C : PLine;
I : Integer;
N : Integer;
S : String;
begin
if (not(BlockContiguous)) or
(not(LongFlagIsSet(beOptions, beBlockOn))) or
(not(CursorInBlock(False))) then exit;
if beBlockBegin.LP = beBlockEnd.LP then exit;
C := CurLine;
DropMarker(C, CurCol);
I := Abs(Spaces);
S := CharStr(' ', I);
P := beBlockBegin.LP;
GetWork(P);
if Spaces > 0 then begin
InsertStr(S, Work^, beBlockBegin.CP);
Status := P^.lnUpdate(Work);
if Status <> 0 then goto Breakout;
CharsInserted(P, beBlockBegin.CP, I);
P := PLine(P^.dlNext);
while (P <> PLine(beBlockEnd.LP^.dlNext)) do begin
if (P <> beBlockEnd.LP) or (beBlockEnd.CP > 0) then begin
GetWork(P);
InsertStr(S, Work^, 0);
Status := P^.lnUpdate(Work);
if Status <> 0 then goto Breakout;
if (P = C) or (P = beBlockEnd.LP) then
CharsInserted(P, 0, I);
end;
P := PLine(P^.dlNext);
end;
end
else begin
N := 0;
while (N < I) and (Work^[beBlockBegin.CP+N] = ' ') do Inc(N);
DeleteAsc(Work^, beBlockBegin.CP, N);
Status := P^.lnUpdate(Work);
if Status <> 0 then goto Breakout;
CharsInserted(P, beBlockBegin.CP, -N);
P := PLine(P^.dlNext);
while (P <> PLine(beBlockEnd.LP^.dlNext)) do begin
if (P <> beBlockEnd.LP) or (beBlockEnd.CP > 0) then begin
GetWork(P);
N := 0;
while (N < I) and (Work^[beBlockBegin.CP+N] = ' ') do Inc(N);
DeleteAsc(Work^, 0, N);
Status := P^.lnUpdate(Work);
if Status <> 0 then goto Breakout;
if (P = C) or (P = beBlockEnd.LP) then
CharsInserted(P, 0, -N);
end;
P := PLine(P^.dlNext);
end;
end;
N := CurCol+Spaces;
if N < 0 then N := 0;
CursorToCol(N);
SetLongFlag(beOptions, beModified+beForceRedraw);
exit;
Breakout:
if Status = 0 then Status := ecOutOfMemory;
GotError(epNonFatal+Status, emInsufficientMemory);
end;
{-----------------------------------------------------------------------------}
procedure BigEditor.TextSearch(Prompt : Boolean; SearchType : beSearchType);
label
ExitPoint;
var
SaveRec : StreamStateRec;
SaveIdx : Integer;
Hits, Replacements : Integer;
TSrch : String[MaxSearchLen];
N : Integer;
YN : Byte;
procedure StUpcaseAsc(P : AsciiZPtr);
var
I : Integer;
begin
i := 0;
while P^[i] <> #0 do begin
P^[i] := UpCase(P^[i]);
Inc(I);
end;
end;
procedure ReplaceText(Curr : AsciiZPtr; Repl : String; Start, Len : Integer);
begin
DeleteAsc(Curr^, Start, Len);
InsertStr(Repl, Curr^, Start);
end;
function NextMatch(StartLine : PLine; Srch : String) : PLine;
{!!.13 - Completely rewritten for better performance and a bug fix}
var P : PLine;
T : String;
W : Word;
begin
NextMatch := NIL;
P := StartLine;
if P = NIL then exit;
while P <> NIL do begin
if NoCase then
W := SearchUC(P^.St^[SaveIdx], P^.Len-SaveIdx-1, Srch[1], Length(Srch))
else
W := Search(P^.St^[SaveIdx], P^.Len-SaveIdx-1, Srch[1], Length(Srch));
if W <> $FFFF then begin
SaveIdx := W;
NextMatch := P;
exit;
end;
SaveIdx := 0;
if Backwards then begin
P := PLine(P^.dlPrev);
Dec(TNum);
end
else begin
P := PLine(P^.dlNext);
Inc(TNum);
end;
end;
end;
begin
{if a reSearch and no prev search performed, quit}
if (NOT(Prompt)) and (SearchType = bescSearch) and (SearchLine = NIL) then
exit;
if (Prompt) then begin
if NOT Edit(0, 'Search for: ', False, False, MaxSearchLen, beSearchSt) then
exit;
if (SearchType = bescReplace) then begin
if NOT Edit(0, 'Replace with: ', False, False, MaxSearchLen, beReplaceSt) then
exit;
end;
if NOT Edit(0, 'Options: ', True, True, MaxSearchOptions, beOptionSt) then
exit;
Replacements := 0;
NoCase := False;
Backwards := False;
NoConfirm := False;
BlockOnly := False;
Global := False;
for N := 1 to Length(beOptionSt) do
case Upcase(beOptionSt[N]) of
beBackward : Backwards := True;
beNoCase : NoCase := True;
beNoConfirm : NoConfirm := True;
beBlockOnly : BlockOnly := True;
beGlobal : Global := Prompt;
end;
end;
{save the current state of the stream}
SaveStatePrim(SaveRec);
SetLongFlag(beOptions, beSearching);
{adjust for case sensitivity}
if NoCase then
TSrch := StUpCase(beSearchSt)
else
TSrch := beSearchSt;
{get the current line to start the search}
SearchLine := CurLine;
SaveIdx := CurCol;
{adjust for Backwards search}
if Backwards then begin
ClearLongFlag(beOptions, beHighlightBack);
Dec(SaveIdx);
end
else begin
SetLongFlag(beOptions, beHighlightBack);
if (SearchType = bescSearch) and (not(Prompt)) then {!!.13}
Inc(SaveIdx); {!!.13}
end;
{if global and not re-search, adjust to top/bottom of stream}
if (Prompt) and (Global) then begin
if Backwards then begin
SearchLine := PLine(LList^.Tail);
SaveIdx := SearchLine^.lnLen;
end
else begin
SearchLine := PLine(LList^.Head);
SaveIdx := 1;
end;
end;
{adjust so SearchLine is the top-of-screen line}
Top := SearchLine;
TNum := LList^.Num(Top);
LOfs := 0;
YN := beYes;
Hits := 0;
{search for next match:}
while True do begin
SearchLine := NextMatch(SearchLine, TSrch);
if (SearchLine = NIL) or
((BlockOnly) and (NOT(LineInBlock(SearchLine)))) then begin
if (SearchType <> bescReplace) or (Hits = 0) then
GotError(epNonFatal+ecStringNotFound, emStringNotFound);
goto ExitPoint;
end;
Inc(Hits);
{make it displayable}
Top := SearchLine;
TNum := LList^.Num(Top);
LOfs := 0;
{try to center the line in the screen}
while (Top^.dlPrev <> NIL) and (LOfs < (Height div 2)) do begin
Top := PLine(Top^.dlPrev);
Dec(TNum);
Inc(LOfs);
end;
{position the cursor}
if Backwards then
CursorToCol(SaveIdx)
else
CursorToCol(SaveIdx+Length(beSearchSt)-1);
SetLongFlag(beOptions, beForceRedraw);
UpdateContents;
SaveStatePrim(SaveRec);
if SearchType = bescSearch then begin
while NOT cwCmdPtr^.cpKeyPressed do ;
goto ExitPoint;
end
else begin
if NOT NoConfirm then begin
YN := YesNo(0, 'Replace?', beNo, True);
NoConfirm := (YN = beAll);
if (YN = beQuit) then
goto ExitPoint;
end;
if YN <> beNo then begin
GetTemp(SearchLine); {!!.13}
ReplaceText(Temp, beReplaceSt, SaveIdx, Length(beSearchSt));
Status := SearchLine^.lnUpdate(Temp);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
goto ExitPoint;
end;
inc(Replacements);
SetLongFlag(beOptions, beForceRedraw);
UpdateContents;
end;
if Backwards then
Dec(SaveIdx)
else if Length(beReplaceSt) > Length(beSearchSt) then
Inc(SaveIdx, Length(beReplaceSt))
else
Inc(SaveIdx, Length(beSearchSt));
end;
end;
ExitPoint:
RestoreStatePrim(SaveRec);
if (SearchType = bescReplace) and (Replacements > 0) then
SetLongFlag(beOptions, beModified);
ClearLongFlag(beOptions, beSearching);
SetLongFlag(beOptions, beForceRedraw);
UpdateContents;
end;
{----------------------------------------------------------------------------}
procedure BigEditor.ReformatParagraph;
label
BreakOut;
var
B, X, Q : Integer;
P, N : PLine;
begin
if not LongFlagIsSet(beOptions, beWordWrap) then exit;
{get the current line}
Q := 0;
GetCurLine;
B := LeadingWhite(Cur);
P := Cur;
{skip white lines}
while (P^.dlNext <> nil) and (P^.lnLen = 0) do begin
P := PLine(P^.dlNext);
ChLine(1);
end;
if P^.dlNext = nil then
exit;
{run the loop}
while (P <> nil) and (P^.lnLen > 0) do begin
GetWork(P);
{pull up lines as needed to make a line > margin length}
if P^.lnLen <= beMargin+1 then repeat
N := PLine(P^.dlNext);
if (N = nil) then goto Breakout;
if N^.lnLen > 0 then begin
AscTrim(N^.St^, Temp^);
InsertStr(' ', Temp^, 0);
Status := N^.lnUpdate(Temp);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
ConcatAsc(Work^,N^.St^,Temp^);
MoveFast(Temp^,Work^,LenAsc(Temp^)+1);
LList^.Delete(N);
end;
until (LenAsc(Work^) > beMargin+1) or (N^.lnLen = 0);
{wrap the line and update it}
WordWrap(Work, Temp, beMargin);
Status := P^.lnUpdate(Work);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory,emInsufficientMemory);
exit;
end;
AscTrimLead(Temp^, Work^);
if LenAsc(Work^) = 0 then begin
ChLine(1);
goto Breakout;
end;
if B > 0 then
InsertStr(CharStr(' ', B), Work^, 0);
{add the ovrlap line to the list}
New(N,Init(Work));
if N = nil then begin
GotError(epNonFatal+ecOutOfMemory,emInsufficientMemory);
exit;
end;
LList^.Place(N,P);
P := PLine(P^.dlNext);
ChLine(1);
Inc(Q);
end;
BreakOut:
GetCurLine;
CursorToCol(Cur^.lnLen);
CleanBlocking;
SetLongFlag(beOptions, beModified+beForceRedraw);
end;
procedure BigEditor.ReformatGlobal;
var S : StreamStateRec;
P : PLine;
begin
if not LongFlagIsSet(beOptions, beWordWrap) then exit;
SaveStatePrim(S);
P := LList^.OfsLine(Top,LOfs);
while P^.dlNext <> nil do begin
ReformatParagraph;
UpdateContents;
P := LList^.OfsLine(Top,LOfs);
end;
RestoreStatePrim(S);
SetLongFlag(beOptions, beModified+beForceRedraw);
end;
procedure BigEditor.CenterLine;
var
I, J, Delta, Len : Integer;
begin
GetCurLine;
if Cur^.lnLen = 0 then exit;
{find the first non-blank}
I := LeadingWhite(Cur);
{length of actual text in string}
Len := Cur^.lnLen-I;
{can it be centered?}
if Len >= beMargin then begin
if I > 1 then begin
{can't center it, but we can move it to the left margin}
DeleteAsc(Work^, 0, I);
CharsInserted(Cur, 0, -I);
end;
end
else begin
{calculate new starting column}
J := (beMargin-Len) shr 1;
Delta := J-I;
if Delta > 0 then begin
{insert extra spaces at beginning of line}
InsertStr(CharStr(' ', Delta), Work^, 0);
CharsInserted(Cur, 0, Delta);
end
else if Delta < 0 then begin
{delete extra spaces at beginning of line}
DeleteAsc(Work^, 0, Delta);
CharsInserted(Cur, 0, -Delta);
end;
end;
{update the line}
Status := Cur^.lnUpdate(Work);
if Status <> 0 then begin
GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
exit;
end;
CursorToCol(Cur^.lnLen);
SetLongFlag(beOptions, beModified);
end;
{---------------------------------------------------------------------------}
{$IFDEF UseScrollBars}
procedure BigEditor.UpdateScrollBars;
{-Update horizontal and vertical scroll bars}
begin
if LList^.Size <> SaveCnt then begin
ChangeAllScrollBars(0, (AbsMaxAsciiZ-Width-1), 1, LList^.Size);
SaveCnt := LList^.Size;
end;
DrawAllSliders(COfs, TNum+LOfs);
end;
{$ENDIF}
procedure BigEditor.AdjustCursorToWindow;
{-when resizing, make sure CurLine and cursor are within window}
var
X : Integer;
begin
while LOfs > Height-1 do
ChLine(-1);
X := CurCol;
while (X) > Width do begin
Dec(X);
CursorToCol(X);
end;
end;
{$IFDEF UseMouse}
function BigEditor.ProcessMouseCommand(Cmd : Byte) : Boolean;
{-Process ccMouseSel/Auto command. Returns True to return control to user.}
var
L : LongInt;
FramePos : FramePosType;
HotCode : Byte;
NeedUp, NeedDn : Boolean;
procedure MouseSelect;
{-Move cursor to position of mouse}
var
I : Integer;
begin
Cur := Top;
I := MouseKeyWordY+MouseYLo-wYL;
if I < LOfs then
LOfs := I
else begin
Cur := CurLine;
while LOfs < I do
if Cur^.dlNext <> nil then begin
Cur := PLine(Cur^.dlNext);
Inc(LOfs);
end
else Dec(I);
end;
I := MouseKeyWordX+MouseXLo-Pred(wXL)-1;
if I < 0 then I := 0;
CursorToCol(I);
if beOptionsAreOn(beHighlightCurr) then
SetLongFlag(beOptions, beForceRedraw);
end;
begin
ProcessMouseCommand := False;
NeedUp := False;
NeedDn := False;
{determine position of mouse}
EvaluateMousePos;
L := PosResults(FramePos, HotCode);
case HotCode of
hsNone : {not a hot spot}
case FramePos of
frInsideActive : {inside window}
MouseSelect;
frTL..frRR : {on the frame}
ProcessMouseCommand := (LongFlagIsSet(wFlags, wAllMouseEvents)) and
(Cmd <> ccMouseAuto);
frInsideFrame, {inside window frame but not in window boundaries}
frOutsideFrame : {outside window frame}
ProcessMouseCommand := (LongFlagIsSet(wFlags, wAllMouseEvents)) and
{don't let an auto kick us out}
(Cmd <> ccMouseAuto);
end;
{$IFDEF UseScrollBars}
hsDecV : {the decrement fixture of a vertical scroll bar}
if LongFlagIsSet(beOptions, beMousePage) then
ChTopLine(-(Height-1))
else
ChLine(-1);
hsDecH : {the decrement fixture of a horizontal scroll bar}
if COfs > 0 then begin
Dec(COfs);
SetLongFlag(beOptions, beForceRedraw);
end;
hsIncV : {the increment fixture of a vertical scroll bar}
if LongFlagIsSet(beOptions, beMousePage) then
ChTopLine(Height-1)
else
ChLine(1);
hsIncH : {the increment fixture of a horizontal scroll bar}
if COfs < (AbsMaxAsciiZ - Width) then begin
Inc(COfs);
SetLongFlag(beOptions, beForceRedraw);
end;
hsBar : {the slider portion of a scroll bar}
case FramePos of
frLL, frRR : {vertical scroll bar}
begin
L := TweakSlider(FramePos, MouseKeyWordY+MouseYLo, L, 1);
if L <= 1 then
{goto top of file}
TopOfFile
else begin
if L >= LList^.Size then
{goto end of file}
EndOfFile
else
{goto specified line}
GoToLineNum(Integer(L));
end;
end;
else begin {horizontal scroll bar}
COfs := TweakSlider(FramePos, MouseKeyWordX+MouseXLo, L, 1);
SetLongFlag(beOptions, beForceRedraw);
end;
end;
{$ENDIF}
hsSpot, {a single character hot spot}
hsRegion0..255 : {a user-defined region relative to a frame}
{$IFDEF UseDrag}
begin
if NOT(HandleMousePress(Self) in [MoveHotCode, ResizeHotCode, ZoomHotCode]) then
ProcessMouseCommand := (Cmd <> ccMouseAuto);
AdjustCursorToWindow;
SetLongFlag(beOptions, beForceRedraw);
if LongFlagIsSet(beOptions, beInsert) then
FatCursor
else
NormalCursor;
end;
{$ELSE}
ProcessMouseCommand := (Cmd <> ccMouseAuto);
{$ENDIF}
end;
end;
{$ENDIF}
procedure BigEditor.beUpdateContents;
var
S : String;
SLen : Byte absolute S;
A : String;
ALen : Byte absolute A;
P : PLine;
I : Integer;
Wid : Byte;
Hit : Byte;
B : Boolean;
procedure DispStr(P : PLine; Ofst : Integer);
var
W, X, Y : Integer;
begin
FillChar(S[1], Wid, ' ');
SLen := Wid;
if (LongFlagIsSet(beOptions, beHighlightCurr)) and (Ofst = LOfs) then
FillChar(A[1], Wid, HA)
else
FillChar(A[1], Wid, TA);
ALen := Wid;
if P = nil then exit;
W := P^.lnLen;
if (W <> 0) and (W >= COfs) then begin
if (W - COfs) >= Wid then
MoveFast(P^.St^[COfs], S[1], Wid)
else if (W - COfs) > 0 then
MoveFast(P^.St^[COfs], S[1], W - COfs);
end;
{fixup blocking}
if LongFlagIsSet(beOptions, beBlockOn) then
if P^.Blocked then begin
if P = beBlockBegin.LP then begin
if P = beBlockEnd.LP then begin
X := beBlockBegin.CP - COfs + 1;
if X < 1 then X := 1;
Y := (beBlockEnd.CP - COfs + 1) - X;
if Y >= Wid then
Y := Wid;
if (Y > 0) then
FillChar(A[x], Y, BA);
end
else begin
if COfs >= beBlockBegin.CP then
FillChar(A[1], Wid, BA)
else begin
X := beBlockBegin.CP-COfs+1;
if X > 0 then
FillChar(A[x], Wid, BA);
end;
end;
end
else if P = beBlockEnd.LP then begin
if COfs < beBlockEnd.CP then
FillChar(A[1], beBlockEnd.CP-COfs, BA);
end
else
FillChar(A[1], Wid, BA);
end;
{fixup ctrl chars}
for X := 1 to Wid do begin
if S[x] < #32 then begin
S[x] := Chr(Byte(S[x]) or $40);
A[x] := Chr(CA);
end;
end;
if LongFlagIsSet(beOptions, beSearching) and (P = SearchLine) then begin
X := CurCol;
if LongFlagIsSet(beOptions, beHighlightBack) then
FillChar(A[X-Length(beSearchSt)+2], Length(beSearchSt), MA)
else
FillChar(A[X+1], Length(beSearchSt), MA);
end;
{fixup beMarkers}
if LongFlagIsSet(beOptions, beMarkersOn) then
for X := 0 to MaxMarker do
if beMarkers[x].LP = P then begin
Y := beMarkers[x].CP - COfs;
if (Y > 0) and (Y <= Wid) then begin
S[y] := Chr(X + ord('0'));
A[y] := Chr(MA);
end;
end;
end;
begin
Wid := Width;
{$IFDEF UseMouse}
HideMousePrim(B);
{$ENDIF}
if LongFlagIsSet(beOptions, beForceRedraw) then begin
{redraw the whole screen}
P := Top;
for I := wYL to wYH do begin
DispStr(P, I-wYL);
FastWriteAttr(S, I, wXL, A);
if P <> nil then
P := PLine(LList^.Next(P));
end;
end
else begin
{redraw just the current line}
P := CurLine;
DispStr(P, LOfs);
FastWriteAttr(S, wYL+LOfs, wXL, A);
{account for highlighting}
if LongFlagIsSet(beOptions, beHighlightCurr) then begin
if LOfs > 0 then begin
DispStr(PLine(P^.dlPrev), LOfs-1);
FastWriteAttr(S, wYL+LOfs-1, wXL, A);
end;
if LOfs < Hit-1 then begin
DispStr(PLine(P^.dlNext), LOfs+1);
FastWriteAttr(S, wYL+LOfs+1, wXL, A);
end;
end;
end;
GoToXYAbs(wXL+CPos-1, wYL+LOfs);
if LongFlagIsSet(beOptions, beInsert) then
FatCursor
else
NormalCursor;
{$IFDEF UseScrollBars}
UpdateScrollBars;
{$ENDIF}
if @beStatus <> nil then
beStatus(@Self);
{$IFDEF UseMouse}
ShowMousePrim(B);
{$ENDIF}
ClearLongFlag(beOptions, beForceRedraw);
end;
procedure BigEditor.UpdateContents;
begin
beUpdateContents;
StackWindow.UpdateContents;
end;
procedure BigEditor.NewFilePrompted;
var
PS : PathStr;
FS : LongInt;
begin
PS := bePathName;
if GetFile(0, 'New path:', True, True, False, False,
80, beDefExt, PS) and(PS <> bePathName) then begin
if LongFlagIsSet(beOptions, beModified) then
if YesNo(0, 'Current file modified. Save?', beYes, False) = beYes then
SaveFile;
ReadFile(PS, FS);
SetLongFlag(beOptions, beForceRedraw);
end;
end;